# -*- coding:Utf-8 -*-
'''
Created on 25 nov. 2012

@author: fefoley
'''
import codecs
import datetime, calendar

from workday import WorkDay
from timestrip import DatetimeInterval, DatetimeIntervalSet, TimestripSet


input_root_path = "C:\\Users\\famille\\Desktop\\analyses mails\\reverse_hours.io\\"
path2f1 = input_root_path + 'brut holiday.txt'
path2f2 = input_root_path + 'net holiday.txt'


def days_of_week(year, week):
    day = datetime.date(year, 2, 1)
    year, weekBase, dayBase = day.isocalendar()
    day += datetime.timedelta(1 - dayBase + (week - weekBase)*7)
    delta = datetime.timedelta(1)
    for i in range(6):
        yield day
        day += delta
    yield day


def wddico_init(startday, endday):
    """init a dictionary of days, from startday to endday included"""
    startyear = startday.year
    endyear = endday.year
    
    wddico = {}
    for y in range(startyear, endyear+1):
        nb_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        if calendar.isleap(y): nb_days[1] = 29
        
        'must be complete months for the given years, with empty workday if out of range(startday, endday)'
        'empty wddico'
        wddico[y] = [[None for d in range(0,nb_days[m])] for m in range(0,12)]
    
    'set the workdays'
    for y in wddico.keys():
        nb_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        if calendar.isleap(y): nb_days[1] = 29        
   
        for m in range(0,12):
            for d in range(0, nb_days[m]):
                if datetime.datetime(y, m+1, d+1) >= startday \
                   and datetime.datetime(y, m+1, d+1) <= endday:
                    
                    'set current day'
                    wddico[y][m][d] = WorkDay(datetime.datetime(y, m+1, d+1))
                    
                    'set link to previous day and for previous day,the link to the next = this current day'
                    if d == 0 and m == 0 and y-1 not in wddico.keys():
                        wddico[y][m][d].previous = None 
                    elif d == 0 and m == 0 :
                        wddico[y][m][d].previous = wddico[y-1][12-1][31-1]
                        if wddico[y-1][12-1][31-1]:
                            wddico[y-1][12-1][31-1].next = wddico[y][m][d]
                    elif d == 0:
                        wddico[y][m][d].previous = wddico[y][m-1][nb_days[m-1]-1]
                        if wddico[y][m-1][nb_days[m-1]-1]:
                            wddico[y][m-1][nb_days[m-1]-1].next = wddico[y][m][d]
                    else :
                        wddico[y][m][d].previous = wddico[y][m][d-1]
                        if wddico[y][m][d-1]:
                            wddico[y][m][d-1].next = wddico[y][m][d]
                                      
    return wddico


def weekdico_init(startday, endday, wddico):
    """Init a dictionnary of weeks and days, from startday to endday inluded.    """
    
    'startday and endday --> which years are we talking about?'
    startyear = startday.year
    endyear = endday.year   
    
    'determine the number of weeks for each year'
    nb_weeks = {}
    for y in range(startyear, endyear+1):
        theyear, theweek, theweekday = datetime.date(y, 1, 1).isocalendar()
        if theyear == y:
            _, nb_weeks[y], _ = (datetime.date(y, 1, 1) - datetime.timedelta(theweekday)).isocalendar()
        else :
            nb_weeks[y] = theweek
    
    'initialize the week dico'
    weekdico = {}
    for y in range(startyear, endyear+1):
        weekdico[y] = [[None for _ in range(0,7)] for _ in range(0, nb_weeks[y])]   
    
    'fill it up'
    iterday = startday
    while iterday < endday:
            year, week, weekday = iterday.isocalendar()
            weekdico[year][week-1][weekday-1] = wddico_getday(wddico, iterday)
            iterday += datetime.timedelta(1)    

    return weekdico



def wddico_getday(wddico, adate):
    """proc to return the corresponding WorkDay to a given datetime.date"""
    y = adate.year
    m = adate.month
    d = adate.day
    if y in wddico: return wddico[y][m-1][d-1]
    return []


def openhours(timestrip):
    """Function that return the number of open hours n the timestrip. French regulation.    """
    HOstart = datetime.time(6, 0, 0)
    HOend = datetime.time(22, 0, 0)
    sumhours = 0.0
    
    'how many days in this timestrip ?'
    dtstart = dtiter = timestrip.dtstart
    dtend = timestrip.dtend
    if dtstart > dtend: return 0.0
    
    'compute the HO intervales'
    HOintervals = DatetimeIntervalSet()
    while dtiter <= dtend:
        HOintervals.insert(DatetimeInterval(datetime.datetime.combine(dtiter.date(), HOstart),
                                            datetime.datetime.combine(dtiter.date(), HOend)))
        dtiter += datetime.timedelta(days=1)
    
    'intersect the timestrip with the HOinterval'
    intersection = TimestripSet(timestrip) & HOintervals
    
    'converted to minutes'
    for interval in intersection:
        l = interval.length()
        sumhours += l.days * 24 + l.seconds / 3600.0
    return sumhours

def closedhours(timestrip):
    """Function that return the number of closed hours in the timestrip. French regulation.    """
    HNOstart = datetime.time(22, 0, 0)
    HNOend = datetime.time(6, 0, 0)
    sumhours = 0.0
    
    'how many days in this timestrip ?'
    dtstart = dtiter = timestrip.dtstart
    dtend = timestrip.dtend
    if dtstart > dtend: return 0.0
    
    'compute the HO intervales'
    HNOintervals = DatetimeIntervalSet()
    while dtiter <= dtend:
        HNOintervals.insert(DatetimeInterval(datetime.datetime.combine(dtiter.date(), datetime.time(0, 0, 0)), 
                                            datetime.datetime.combine(dtiter.date(), HNOend)))
        HNOintervals.insert(DatetimeInterval(datetime.datetime.combine(dtiter.date(), HNOstart), 
                                            datetime.datetime.combine(dtiter.date(), datetime.time(23, 59, 59))))
        dtiter += datetime.timedelta(days=1)
                    
    'intersect the timestrip with the HOinterval'
    intersection = TimestripSet(timestrip) & HNOintervals
    
    'converted to minutes'
    for interval in intersection:
        l = interval.length()
        sumhours += l.days * 24 + l.seconds / 3600.0
    return sumhours

def convertdate(path2f1, path2f2):

    f1 = open(path2f1, 'r')
    f2 = open(path2f2, 'w')
    
    months = ['Janvier', 'Février','Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre']
    
    for line in f1:
        linesplit = line.split('\t')
        strdate, strferie = linesplit[:2]
        nomjour, nbjour, nommois, annee = strdate.split()
        nbmois = months.index(nommois) + 1
        strout = "{0:02d}/{1:02d}/{2:d}\t{3}\n".format(int(nbjour), int(nbmois), int(annee), strferie)
        f2.write(strout)
        
    f1.close()
    f2.close()
    
class Str2sum:
    """a simple string "label" with a concatenation character "concat".   """
    def __init__(self, label, concat=' + '):
        self.label = label
        self.concat = concat
        
    def __add__(self, other):
        if self.label == other.label:
            return Str2sum(self.label, self.concat)
        else:
            return Str2sum(self.label + self.concat + other.label, self.concat)
    
    def __str__(self):
        return self.label.__str__()
    
    def __repr__(self):
        return self.label.__repr__()


if __name__ == "__main__":

    str_start = "01/09/2011"
    str_end = "31/05/2012"
    
    wdstart =  datetime.datetime.strptime(str_start, "%d/%m/%Y")
    wdend = datetime.datetime.strptime(str_end, "%d/%m/%Y")
    
    'get the workday dico'
    wddico = wddico_init(wdstart, wdend)
    
    'get the corresponding week dico'
    weekdico = weekdico_init(wdstart, wdend, wddico)
    
    print(weekdico)



